import type { CSSProperties, FunctionalComponent } from 'vue'
import type { HeaderCellProps, ColumnType } from '../types'

import { inject, renderSlot } from 'vue'
import clsx from 'clsx'
import { merge, omit } from 'lodash-es'
import { TABLE_SLOT_KEY } from '../context'
import { DEFAULT_HEADER_CELL_ALIGNMENT } from '../../grid/constants'

const HeaderCellRenderer: FunctionalComponent<HeaderCellProps> = (props) => {
  const slots = inject(TABLE_SLOT_KEY)
  const {
    column,
    columnIndex,
    className,
    style,
    key,
    mousedownHandler,
    mousemoveHandler,
    mouseoutHandler
  } = props

  /**
   * 处理column.customCell
   */
  const getCustomCell = (column: ColumnType) =>
    typeof column.customHeaderCell === 'function' ? column.customHeaderCell({ column }) : {}
  /**
   * 处理class
   * 注意column.customCell中返回的class在这里处理
   */
  const getCellClass = (column: ColumnType) => {
    const customCell = getCustomCell(column)
    return clsx(
      'virtualized-grid-cell',
      'virtualized-grid-cell-header',
      { 'virtualized-grid-cell-multiple': column.children && column.children.length > 0 },
      className,
      column.headerCellClassName,
      customCell.class
    )
  }

  const getCellChildClass = (column: ColumnType) => {
    return clsx('virtualized-grid-cell-child', {
      'virtualized-grid-cell-multiple': column.children && column.children.length > 0
    })
  }
  /**
   * 处理style
   * 注意column.customCell中返回的style在这里处理
   */
  const getCellStyle = (column: ColumnType) => {
    const customCell = getCustomCell(column)
    const styl: CSSProperties = merge({}, customCell.style)
    if (column.children && column.children.length > 0 && style) {
      Reflect.deleteProperty(style, 'width')
    }
    return merge(styl, style)
  }

  const getCellChildStyle = (column: ColumnType) => {
    const customCell = getCustomCell(column)
    const styl: CSSProperties = merge({}, customCell.style)
    if (column.children && column.children.length > 0) {
      Reflect.deleteProperty(styl, 'width')
    } else {
      styl.width = column.width + 'px'
    }
    return styl
  }

  const getTextAlign = (column: ColumnType) => {
    const style: CSSProperties = {
      justifyContent: column.align || DEFAULT_HEADER_CELL_ALIGNMENT
    }
    return style
  }

  const renderContent = (column: ColumnType) => {
    const content = renderSlot(
      slots,
      'headerCell',
      { column, columnIndex, title: column.title },
      () => {
        return column.headerCellRender
          ? [column.headerCellRender(column, columnIndex, column.title)]
          : [<span>{column.title}</span>]
      }
    )
    return (
      <div class="virtualized-grid-cell-header-content" style={getTextAlign(column)}>
        {content}
      </div>
    )
  }

  const renderChildren = (children: ColumnType[]) => {
    return (
      <div class="virtualized-grid-cell-children">
        {children.map((child) => (
          <div
            role="cell"
            key={child.field}
            class={getCellChildClass(child)}
            style={getCellChildStyle(child)}
            {...omit(getCustomCell(child), ['class', 'style'])}
          >
            {renderContent(child)}
            {child.children && child.children.length > 0 && renderChildren(child.children)}
          </div>
        ))}
      </div>
    )
  }

  return (
    <div
      role="cell"
      aria-colindex={columnIndex}
      key={key}
      class={getCellClass(column)}
      style={getCellStyle(column)}
      {...omit(getCustomCell(column), ['class', 'style'])}
      onMousedown={(event) => mousedownHandler(event, column)}
      onMousemove={(event) => mousemoveHandler(event, column)}
      onMouseout={mouseoutHandler}
    >
      {renderContent(column)}
      {column.children && column.children.length > 0 && renderChildren(column.children)}
    </div>
  )
}

HeaderCellRenderer.displayName = 'HeaderCellRenderer'

export default HeaderCellRenderer
